perm filename LECT6.TEX[ARK,TEX] blob
sn#766832 filedate 1984-08-21 generic text, type C, neo UTF8
COMMENT ā VALID 00008 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 % copyright 1984 by Arthur Keller ... All rights reserved
C00004 00003 \section{Defining Macros}
C00006 00004 \section{Defining Macros in Terms of Other Macros}
C00008 00005 \section{A Sample Macro}
C00016 00006 \section{A Macro With Parameters}
C00029 00007 \section{A Few Final Comments}
C00032 00008 \section*{Assignment}
C00036 ENDMK
Cā;
% copyright 1984 by Arthur Keller ... All rights reserved
\chapter{Sample application: a report}
%Tue, August 21
%11am-12n
%Sample application: a report
%>Designing parts of a document
%>TeX code for your design
%>Writing macros to make it easier
%1-2pm
%<lab assignment 4>
The purpose of this lecture is to learn more about macros, what they are
and how they work.
We have already learned how to modify a set of macro packages written by
someone else in order to adapt it to our own uses.
Now we want to learn something about writing our own macros.
Of course, at this point we do not know all that much about the details of
\TeX, so we are not necessarily aware of all the problems which might be
encountered!
We will learn more about \TeX\ fundamentals in the next lecture.
\section{Defining Macros}
As we have already seen, to define a macro, we give the command
\par\smallskip
\noindent
\cmd{def\bs macroname {\sl optional template} \lb {\sl definition\/}\rb}
\par\smallskip
\noindent where
the {\sl optional template} is used for a macro with parameters, and where
{\sl definition} consists of the text and/or commands which \TeX\ is to
substitute for the macro when you give the command \cmd{macroname}.
When you define a macro, \TeX\ reads and parses the definition, but {\sl
does not} check it for validity or do anything else; it merely stores it for
the rest of that run of \TeX\ (or until the end of the current local
grouping, if the macro was defined within a grouping and was not labelled
``global'').
When you call the macro by giving the command \cmd{macroname}, \TeX\ then
pulls the definition it stored out of its memory and inserts it in place
of the command.
(If \cmd{macroname} has parameters, \TeX\ will also try to match the
arguments you have supplied to its template at this time.)
Only at this time will any errors that may have crept in to the definition
be uncovered.
\section{Defining Macros in Terms of Other Macros}
There are two ways to define one macro to be the same as another; however,
they do not have exactly identical effects.
The first way is to type \cmd{def\bs mac\lb\bs macroname\rb}; the second
is to say \cmd{let\bs mac=\bs macroname}.
In the first case, \cmd{mac} is defined to consist of \cmd{macroname}.
In this case, if we change the definition of \cmd{macroname} at any point,
the definition of \cmd{mac} will change as well, indirectly.
This is true because \cmd{mac} refers to whatever the current definition
of \cmd{macroname} happens to be.
In the second case, the definition of \cmd{macroname} in effect {\sl at
the time that the \cmd{let\bs mac=\bs macroname} command is given} is
copied into \cmd{mac}.
Subsequent changes to the definition of \cmd{macroname} {\sl will not}
affect the definition of \cmd{mac}, just as changing the appearance of an
original paper document does not change the appearance of any photocopies
that were made.
\section{A Sample Macro}
Suppose we want to write a macro which will create paragraphs which have
each line slightly indented from the left margin and where there is a
black dot (known as a ``bullet'') opposite the first line of each
paragraph.
How would we do this?
Let us first figure out what commands we would give \TeX\ to get it to do
this once.
Once we've done that, it's easy to write a macro, which is really just a
way of giving that series of commands a name so that it can be easily
executed.
To get the lines of text in each paragraph indented, we will make use of
the command \cmd{hangindent}, which tells \TeX\ to indent each line of a
paragraph after the first by a specific amount of space (which can be
negative).
In fact, it is also possible to get each line after the second, third,
etc. by using the companion command \cmd{hangafter} which tells \TeX\ to
start the indentation after a specific line in each paragraph; if we do
not specify a value for \cmd{hangafter}, \TeX\ assumes a value of 1.
Thus, one of our commands will be \cmd{hangindent = 18pt}.
What about the first line of each paragraph?
We are going to create an \cmd{hbox}, which is a horizontal box of a
specified size, which will contain the bullet and enough blank space to
have the first line of text come out even with the succeeding lines.
In fact, the specific command will be \cmd{hbox to 18pt\lb \$\bs
bullet\$\bs hfill\rb}, which will create a horizontal box 18 points wide,
containing the bullet and the command \cmd{hfill}, which will cause the
bullet to be flush left in the box.
(We will learn more about \cmd{hfill} in the next lecture.)
Notice that since the bullet is in one of \TeX's mathematical fonts of
type, we have to ask for it in math mode.
Since the width of the \cmd{hbox} is the same as the amount of indentation
we have asked for with \cmd{hangindent}, the first line of text will begin
at the directly above the second and subsequent lines.
So, thus far our commands are:
\par\smallskip
{\tt\obeycr
\noindent \bs hangindent = 18pt
\bs hbox to 18pt\lb \$\bs bullet\$\bs hfill\rb
}
\par\smallskip\noindent
However, there are a number of other things that we probably want to
include among our commands to ensure that the paragraph comes out looking
the way we want it to.
First, we need to give the command \cmd{noindent} after the
\cmd{hangindent} to turn off the normal paragraph indentation.
Otherwise, \TeX\ will begin a new indented paragraph when it reads the
\cmd{hbox command}.
We probably also want to begin the sequence of commands with \cmd{par},
which tells \TeX\ to finish the current paragraph that it is in.
That way, if we execute the macro while inside a paragraph, or forget to
leave a blank line, \TeX\ will not get confused.
Finally, we want to tell \TeX\ to \cmd{ignorespaces} after the \cmd{hbox};
that will eliminate any extra spaces that might otherwise sneak in between
the macro and the beginning of the text of the paragraph.
Our entire sequence of commands is thus
\par\smallskip
{\tt\obeycr
\noindent\bs par
\bs hangindent = 18pt
\bs noindent
\bs hbox to 18pt\lb\$\bs bullet\$\bs hfill\rb\%
\bs ignorespaces
}
\par\smallskip
\noindent
and, to convert this into a macro, all we need to do is say
\par\smallskip
{\tt\obeycr
\noindent\bs def\bs bullpar\lb\bs par\dots
\bs ignorespaces\rb
}
\par\smallskip
We can then use this macro by typing \cmd{bullpar} followed by the text of
the paragraph.
The text will come out indented 18 points for the rest of the paragraph
(that is, until \TeX\ sees the next blank line or the next \cmd{par}
command), at which point the normal paragraph style will take over.
If you want more than one of these paragraphs, you need to give the
command \cmd{bullpar} at the beginning of each one.
Once we have worked out the details of the macro, it is relatively easy to
make minor changes in the way the output looks.
For example, if we decide that we want the bullet flush right in the
\cmd{hbox}, separated from the text by an enspace (the width of an
en-dash), we could replace the contents of the \cmd{hbox} with \cmd{hfill
\$\bs bullet\$\bs enspace}, where the \cmd{hfill} now appears before the
\cmd{bullet}, pushing it to the right side of the box until it hits the
\cmd{enspace} separating it from the text.
We have now finished our example of a simple macro without parameters; now
on to bigger and better (or at least fancier) things!
\section{A Macro With Parameters}
This time we are going to create a macro to print a numbered section
heading in a document.
We will follow the same procedure as in the last example:
first figure out what sequence of commands we need to give to get the
output that we want, then turn it into a macro.
However, this this case, since we want the macro to do a slightly
different thing each time it is used (unless all sections have the same
heading and number!), we will create a macro with parameters.
The parameters will tell the macro what name and number we want for each
heading.
Here are some of the characteristics we want our section heading to have:
\begin{itemize}
\item The heading and number should be in boldface and appear in a larger
font.
\item There should be extra space above and below the heading, with more
above than below.
\item The paragraph after the heading should be flush left (not indented).
\item There should never be a page break inside the heading.
\item \TeX\ should be allowed to start a new page before, but not after,
the heading.
\end{itemize}
We already know how to do most of these things; the only new concept
involved is \cmd{penalty}, which tells \TeX\ how desirable or undesirable
a given place is to start a new page.
A high value for \cmd{penalty} indicates a worse page-break, with
\cmd{penalty = 10000} ensuring that \TeX\ will never break a page there; a
low or negative value means that a page-break is okay.
Thus, to get our section heading, we need the following commands:
\par\smallskip
\begin{tabbing}
\tt\bs par~~~~~~~~~~~~~~\=\rm {\tt\%} finishes previous paragraph\\
\tt\bs penalty -100 \>\rm{\tt\%} a good place to break page\\
\tt\bs bigskip \>\rm{\tt\%} puts space above heading\\
\tt\bs vbox\lb\bs noindent\lb\bs headfont 5. \bs quad A Sample Heading\bs par\rb\rb\\
\tt\bs penalty 10000 \>\rm{\tt\%} inhibits pagebreak here\\
\tt\bs medskip \>\rm{\tt\%} space below the heading, less than above\\
\tt\bs noindent \>\rm{\tt\%} next paragraph flush left\\
\tt\bs ignorespaces \>\rm{\tt\%} ignore extra spaces\\
\end{tabbing}
\par\smallskip
\noindent This is all relatively straightforward, except for the long line
with the \cmd{vbox}; let us look at it more closely.
The \cmd{vbox} creates a vertical box which cannot be broken across pages,
thus ensuring that the entire heading will appear on the same page.
After the \cmd{noindent}, which ensures that the section number will be
printed flush left, we have brackets which enclose the text to be printed
in the font \cmd{headfont}, which presumably has been defined somewhere
else in our text as the font to use for headings.
That text consists of `5.', the section number, \cmd{quad}, which puts an
emspace (the width of an em-dash) after the number, and the text of the
heading.
The last thing inside the \cmd{vbox} is a \cmd{par} command, which is
there to ensure that \TeX\ gets the \cmd{baselineskip} right.
How does a \cmd{par} command affect the \cmd{baselineskip}? To understand
this, you have to know a little about how \TeX\ turns paragraphs into lines
(the subject of Chapter 14 in the {\sl \TeX book}). Esentially, \TeX\ reads
a whole paragraph, keeps reading until it sees the beginning of the next
paragraph (or something else which ends a paragraph, like a \cmd{vbox},
and only then outputs the paragraph it just finished reading. Furthermore,
\TeX\ decides on the \cmd{baselineskip} for a paragraph at the time that it
outputs it, based on the last text that it saw.
The \cmd{par} after the section heading ensures that \TeX\ will end the
current paragraph {\sl before} it goes out of \cmd{headfont}.
If it were not for the \cmd{par} after the section heading, \TeX\ would
exit \cmd{headfont}, then end the paragraph when it saw the \cmd{penalty},
by which time it would be back into normal 10-point (or whatever the
default is), and would set the \cmd{baselineskip} accordingly, rather than
setting it to a larger value more appropriate to a bigger font.
This may not make a whole lot of difference for a one-line heading
surrounded by space, but as a general rule {\sl if a whole paragraph is in
some special font, you should always end the paragraph before exiting that
font}.
A few more comments about the \cmd{vbox} before we finish with the macro.
It is important to know that \TeX\ always ends (or ``breaks'') a page
before glue, never after it.
(``Glue'' will be covered in the next lecture; you can think of it as the
space between words, lines, etc.)
Thus, any penalty should be put before the glue, not after it, since \TeX\
would never break there anyway.
Since \TeX\ breaks before the glue, it ignores any glue that would appear
on the top of the next page.
Thus, if a new page began where we said \cmd{penalty -100}, \TeX\ would
throw away the \cmd{medskip} that followed and the heading would appear at
the top of the page.
(It is possible to specify glue that will not be discarded at the top of a
page; one way is to give the command \cmd{null} just before the glue.)
Another way of ensuring that \TeX\ did not break the page after the
section heading would have been to extend the \cmd{vbox} down to the
\cmd{medskip}.
This would not haven prevented a break after the \cmd{medskip}, but since
\TeX\ never breaks after glue, that is not a problem.
However, extending the \cmd{vbox} would cancel out any of the ``stretch''
or ``shrink'' component of the \cmd{medskip}, which might make \TeX's job
harder.
All in all, using a \cmd{penalty} is the best approach.
\newcommand{\heading}[1]{\par\penalty -100\bigskip\vbox{\centerline{\bf #1}
\par}\penalty 1000\medskip\noindent\ignorespaces}
All right, back to the macro.
If we just surrounded our commands so far with braces and gave it a name,
we would get a macro that always printed
\heading{5.\quad A Sample Heading}
which would not be very useful.
Instead, we type
\par\smallskip
{\tt\obeycr
\noindent\bs def\bs heading \# 1 \# 2 \lb\bs par
\bs penalty -100
\bs bigskip
\bs vbox\lb\bs noindent\lb\bs headfont \# 1. \bs quad \# 2\bs par\rb\rb
\bs penalty 1000
\bs medskip
\bs noindent\bs ignorespaces\rb
}
\par\smallskip\noindent
where we have replaced the section number and heading with the parameters
\# 1 and \# 2, respectively.
These parameters appear twice:
once in the {\sl template}, where they tell \TeX\ how the arguments to the
macro will be supplied when it is used, and once in the actual definition
(or {\sl substitute text}, as it is sometimes called), where it tells \TeX\
how to insert the arguments in the text that it will output.
In other words, \TeX\ will take whatever it sees after the command
\cmd{heading} and substitute it in to the definition where the parameters
\# 1 and \# 2 are.
To use the macro, we would type \cmd{heading \lb 6\rb\lb Another Sample
Heading \rb}, and we would get
\heading{6.\quad Another Sample Heading}
Actually, in this case the braces around `6' were not necessary,
since it is a single character, so \TeX\ would have treated it as the
first argument anyway.
However, if we had a section numbered `15' and did not put braces around
the number, \TeX\ would treat the first character it saw, `1', as the
section number, and the second character it saw, `5', as the text of the
heading!
(Notice that we included the period in the definition of the macro, so
that it is only necessary to give the number itself as an argument.
If we were anticipating decimal numbers as section numbers, then that
would not be a good idea, since we would get a section number like `1.5.'
as the result.)
\section{A Few Final Comments}
It is also possible to delimit the parameters of a macro with things other
than braces; however, this is a topic for the very skilled (or very
foolhearty).
Sometimes we do not really need to use parameters at all.
Suppose we want to write a macro called \cmd{line}, which will put the
text which follows it into an \cmd{hbox to \bs hsize} (that is, a
horizontal box the width of the page).
We could use a parameter and say
\par\smallskip
{\tt\obeycr
\noindent\bs def\bs line \# 1\lb\bs hbox to \bs hsize\lb\# 1\rb\rb
}
\par\smallskip\noindent
However, we can simply say
\par\smallskip
{\tt\obeycr
\noindent\bs def\bs line\lb\bs hbox to \bs hsize\rb
}
\par\smallskip\noindent
when \TeX\ substitutes in \cmd{hbox to \bs hsize} for \cmd{line}, it will
be expecting the next thing it sees to be the argument of \cmd{hbox}
anyway.
Thus there is no need to use an explicit parameter.
When writing macros, remember that the brackets which surround the
definition of the macro {\sl disappear} when you use the macro; \TeX\ only
sees the text inside the brackets.
Thus, if you define a macro as follows: \cmd{def\bs bolddate\lb\bs bf\bs
today\rb}, where \cmd{today} is as defined in the \cmd{letterformat} file,
then when you say \cmd{bolddate} \TeX\ will see \cmd{bf\bs today} and go
on typing everthing else in your document in boldface.
What you meant to say was \cmd{def\bs bolddate\lb \lb\bs bf\bs
today\rb\rb}, where the inner set of brackets will ensure that only the
date appears in boldface.
\section*{Assignment}
Reading for this lecture: \TeX book: {\sl Skim} Chapters~11--15.
Assignment for this lecture:
This assignment is based on lab assignment~2 (in Chapter~4).
You should generate the following letter by creating a new file with the
necessary information to produce a letter similar to the one on the next
page.
There is a file called {\tt TeXinputs:laws.tex} which contains
``An Abridged Collection of Interdisciplinary Laws''---laws like
Murphy's law.
The file blah contains a bunch of laws, which look like
\par\smallskip
{\tt\obeycr
\bs law\lb the title of the law\rb
Text of the law---the law may extend over several
lines, like this one, which is very, very, very
long. There is no guarantee that the law will be
on a different line than the title, or that there
will be any blank lines between laws.
}
\par\smallskip
Your job is to write a macro called {\tt \bs{}law} that formats the laws
nicely.
Your macro will need to take a parameter (the title); it should look
something like this:
\par\smallskip
{\tt\obeycr
\noindent \bs def\bs law\#1\lb{\sl your definition}\rb
}
\par\smallskip
You may want to use indentation, paragraph breaking, vertical skip, and
font changes in your macro, although you should feel free to experiment
with \TeX\ to design anything you like.
Here is one possible way to typeset the laws:
\par\smallskip
{\parindent=18pt
\def\law#1{\par\penalty-100\medskip\vbox{\noindent{\bf #1}}
\penalty10000\smallskip}
\law{Kafka's Law} In the fight between you and the world, back the world.
\law{Kamin's First Law}All currencies will decrease in value and
purchasing power over the long term, unless they are freely and fully
convertable into gold and that gold is traded freely without restrictions
of any kind.
\law{Kamin's Second Law} Threat of capital controls accelerates marginal
capital outflows.
\law{Kamin's Third Law} Combined total taxation from all levels of
government will always increase (until the government is replaced by war
or revolution).
}
\medskip
Your file should end with the command \cmd{input laws} to get the file of
laws that we have set up for you.